package com.web.server.common.filters;

import com.fasterxml.jackson.core.*;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Type;

import static com.fasterxml.jackson.databind.SerializationFeature.FAIL_ON_EMPTY_BEANS;

/**
 * Created by ZHANGXIANLIANG1 on 2016/1/26.
 */
public class MappingJackson2JsonpHttpMessageConverter extends MappingJackson2HttpMessageConverter {

    /**
     * JSON 格式前缀，如果前端传递的 前缀不为空，则以JSONP格式返回，否则以JSON格式返回
     */
    private static final String CALLBACK_PREFIX = "callback";

    @Override
    protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
        JsonGenerator generator = this.objectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding);
        objectMapper.disable(FAIL_ON_EMPTY_BEANS);
        try {
            writePrefix(generator, object);
            Class<?> serializationView = null;
            Object value = object;
            if (value instanceof MappingJacksonValue) {
                MappingJacksonValue container = (MappingJacksonValue) object;
                value = container.getValue();
                serializationView = container.getSerializationView();
            }
            if (serializationView != null) {
                this.objectMapper.writerWithView(serializationView).writeValue(generator, value);
            } else {
                this.objectMapper.writeValue(generator, value);
            }
            writeSuffix(generator, object);
            generator.flush();
        } catch (JsonProcessingException ex) {
            throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
        }
    }

    @Override
    protected void writePrefix(JsonGenerator generator, Object object) throws IOException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String callback = request.getParameter(CALLBACK_PREFIX);

        if (!StringUtils.isEmpty(callback)) {
            generator.writeRaw(callback + "(");
        }
    }

    @Override
    protected void writeSuffix(JsonGenerator generator, Object object) throws IOException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String callback = request.getParameter(CALLBACK_PREFIX);

        if (!StringUtils.isEmpty(callback)) {
            generator.writeRaw(")");
        }
    }
}
